package com.novel.controller.other;


import com.novel.common.event.DownLoadInfoEvent;
import com.novel.common.exception.CustomerException;
import com.novel.pojo.novel.Novel;
import com.novel.pojo.novel.NovelChapter;
import com.novel.pojo.novel.NovelShelf;
import com.novel.pojo.system.DownLoadInfo;
import com.novel.pojo.system.User;
import com.novel.service.*;
import com.novel.utils.CodeUtils;
import com.novel.utils.DownloadUtils;
import com.novel.utils.MailUtils;
import com.novel.utils.RegexUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.stream.Collectors;


@Controller
public class CodeController extends BaseController {

    @Autowired
    private NovelService novelService;

    @Autowired
    private NovelChapterService chapterService;

    @Autowired
    private NovelShelfService shelfService;

    @Autowired
    private DownloadUtils downloadUtils;

    @Autowired
    private ApplicationEventPublisher publisher;

    @Autowired
    private MailUtils mailUtils;

    // 写一个方法随机获取颜色
    public Color randomColor() {
        // r g b 取值范围 0到255
        Random random = new Random();
        return new Color(
                random.nextInt(256),
                random.nextInt(256),
                random.nextInt(256));
    }

    /**
     * 发送邮件验证码
     */
    @GetMapping("/sendCode")
    public ResponseEntity<Boolean> sendEmail(String email) throws Exception {
        //验证输入的邮箱是不是邮箱
        if (RegexUtils.isEmail(email)) {
            //判断是否有验证码
            //获得上次发送验证码的是时间
            Date time = (Date) session.getAttribute("time");
            if (time != null) {
                //已经发送过验证码，需要验证是否达到时间
                Date date = new Date();
                long result = date.getTime() - time.getTime();
                if (result <= 60000) {
                    return ResponseEntity.ok(false);
                }
            }   //标记发送时间
            session.setAttribute("time", new Date());
            String code = CodeUtils.getNumsCode(8);
            //设置验证码
            setVarCode(code);
            mailUtils.sendEmail(email, "请输入验证码", code);
            return ResponseEntity.ok(true);
        }
        throw new CustomerException("邮箱格式错误");
    }


    /**
     * 小说下载
     *
     * @param id 小说id
     */
    @PostMapping("/download/{id}")
    @ResponseBody
    public void download(@PathVariable("id") String id) throws IOException {
        //获取用户信息，如果用户没有登录则返回false
        User user = getUserInformation();
        if (user == null) {
            return;
        }
        //获取小说信息
        Novel novel = novelService.findNovelById(id);
        //获取章节信息
        List<NovelChapter> chapterList = chapterService.findChapterByUserId(user.getUserId(), novel.getNovelId());
        //把信息写入文件
        File file = new File(novel.getNovelName() + ".txt");
        //创建文件
        if (!file.exists()) {
            file.createNewFile();
        } else {
            //文件存在，可能是之前有没有删除，也有可能是之前数据比较旧，需要删除后在创建
            file.deleteOnExit();
            file.createNewFile();
        }
        FileWriter fw = new FileWriter(file, true);
        //遍历集合写入数据
        try {
            for (NovelChapter chapter : chapterList) {
                fw.write("\r\n");
                fw.write(chapter.getChapterName());
                fw.write("\r\n");
                fw.write(chapter.getChapterContent());
                fw.write("\r\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            fw.close();
        }
        //监听器提交监听事件
        DownLoadInfo downLoadInfo = DownLoadInfo.builder()
                .createdIp(getUserIpAddress())
                .createdTime(new Date())
                .fileSize(file.length())
                .id(UUID.randomUUID().toString())
                .novelId(novel.getNovelId())
                .userId(user.getUserId())
                .build();
        DownLoadInfoEvent event = new DownLoadInfoEvent(this, downLoadInfo);
        publisher.publishEvent(event);
        //返回数据给页面
        downloadUtils.prototypeDownload(file, file.getName(), response);
        //删除本地文件
        file.delete();
    }

    /**
     * 查询小说是否在书架中
     * 是返回true，不是返回false
     *
     * @param id 小说id
     */
    @GetMapping("/findShelf/{novelId}")
    @ResponseBody
    public ResponseEntity<Boolean> findShelf(@PathVariable("novelId") String id) {
        //获取用户信息
        User user = getUserInformation();
        if (user == null) {
            //用户未登录
            return ResponseEntity.ok(false);
        }
        //查询用户书架信息
        List<NovelShelf> userShelf = shelfService.findUserShelf(user.getUserId());
        //获取所有添加书架书籍的id
        List<String> list = userShelf.stream()
                .map(NovelShelf::getNovelId)
                .collect(Collectors.toList());
        //比较id是否在里面
        boolean flag = list.contains(id);
        //返回结果
        return ResponseEntity.ok(flag);
    }

    /**
     * 添加小说到书架中，如果用户没有登录则自动跳转到登录页面
     *
     * @param id 小说id
     */
    @PostMapping("/addShelf/{novelId}")
    @ResponseBody
    public ResponseEntity<Boolean> addShelf(@PathVariable("novelId") String id) {
        //获取用户信息
        User user = getUserInformation();
        if (user == null) {
            throw new CustomerException("用户未登录");
        }
        //创建书架对象封装信息
        NovelShelf shelf = new NovelShelf();
        shelf.setUserId(user.getUserId());
        shelf.setNovelId(id);
        shelf.setChapterOrder(1);//添加之后默认未第一章
        //添加到书架
        boolean result = shelfService.addNovelToShelf(shelf);
        return ResponseEntity.ok(result);
    }

    /**
     * 根据小说id删除书架
     *
     * @param id 小说id
     */
    @PostMapping("/deleteShelf/{id}")
    @ResponseBody
    public ResponseEntity<Boolean> deleteShelf(@PathVariable("id") String id) {
        //从session中获取用户信息
        User user = getUserInformation();
        //判断用户是否登录，避免用户通过接口来操作
        if (user == null) {
            //用户未登录，抛出异常
            throw new CustomerException("用户未登录");
        }
        //创建书架对象封装数据
        NovelShelf shelf = new NovelShelf();
        shelf.setUserId(user.getUserId());
        shelf.setNovelId(id);
        //删除书架
        boolean result = shelfService.deleteShelf(shelf);
        //返回结果给页面
        return ResponseEntity.ok(result);
    }

    /**
     * 生成图片验证码
     */
    @GetMapping("/imgCode")
    public void ImgCode(HttpServletResponse response) throws IOException {
        // 创建缓存图片：指定宽width=90，高 height=30
        int width = 90;
        int height = 30;
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        // 获取画笔对象
        Graphics g = image.getGraphics();
        // 设置画笔颜色，并且填充矩形区域
        g.setColor(Color.white);
        g.fillRect(0, 0, width, height);
        // 创建可变字符串
        StringBuilder sb = new StringBuilder();
        // 从字符数组中随机得到字符，根据需求添加你需要的字符
        char[] arr = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
                'A', 'B', 'C', 'D', 'N', 'E', 'W', 'b', 'o', 'y'};
        // 创建随机对象
        Random r = new Random();
        for (int i = 0; i < 4; i++) {
            // 随机产生一个索引值
            int index = r.nextInt(arr.length);
            // 根据索引获得随机字符
            char ch = arr[index];
            // 拼接字符
            sb.append(ch);
            // 设置字体，大小为 18
            g.setFont(new Font(Font.DIALOG, Font.BOLD + Font.ITALIC, 18));
            // 设置字的颜色随机
            g.setColor(randomColor());
            // 绘制字符串
            // 7. 将每个字符画到图片上，位置：
            int x = 5 + (i * 20);
            int y = 20;
            g.drawString(String.valueOf(ch), x, y);
        }
        // 将验证码字符串存储会话域中
        setVarCode(sb.toString());
        // 8. 画10条干扰线，线的位置是随机的，x 范围在 width 之中，y 的范围在 height 之中。
        for (int i = 0; i < 10; i++) {
            // 设置颜色随机
            g.setColor(randomColor());
            int x1 = r.nextInt(width + 1);
            int x2 = r.nextInt(height + 1);
            int y1 = r.nextInt(width + 1);
            int y2 = r.nextInt(height + 1);
            g.drawLine(x1, y1, x2, y2);
        }
        // 9. 将缓存的图片输出到响应输出流中
        ImageIO.write(image, "png", response.getOutputStream());
    }

}
